/*
 * Copyright 2019-2025 the original author or authors.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.iiifi.kite.boot.utils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;

import com.iiifi.kite.boot.properties.KiteLocaleProperties;
import com.iiifi.kite.core.spring.SpringContextUtils;
import com.iiifi.kite.core.util.ClassUtils;
import com.iiifi.kite.core.util.StringUtils;
import com.iiifi.kite.configuration.KiteProperties;

import lombok.extern.slf4j.Slf4j;

/**
 * Miscellaneous utilities for web applications.
 *
 * @author kite@iiifi.com 花朝
 */
@Slf4j
public class WebUtils extends org.springframework.web.util.WebUtils {

    private static KiteProperties kiteProperties = SpringContextUtils.getBean(KiteProperties.class);


    private static KiteLocaleProperties kiteLocaleProperties = SpringContextUtils.getBean(KiteLocaleProperties.class);

    /**
     * unknown Header key
     */
    public static final String HEADER_IP_UNKNOWN = "unknown";

    /**
     * 判断是否ajax请求
     * spring ajax 返回含有 ResponseBody 或者 RestController注解
     *
     * @param handlerMethod HandlerMethod
     * @return 是否ajax请求
     */
    public static boolean isBody(HandlerMethod handlerMethod) {
        ResponseBody responseBody = ClassUtils.getAnnotation(handlerMethod, ResponseBody.class);
        return responseBody != null;
    }

    /**
     * 读取cookie
     *
     * @param name cookie name
     * @return cookie value
     */
    public static String getCookieVal(String name) {
        HttpServletRequest request = WebUtils.getRequest();
        Assert.notNull(request, "request from RequestContextHolder is null");
        return getCookieVal(request, name);
    }

    /**
     * 读取cookie
     *
     * @param request HttpServletRequest
     * @param name cookie name
     * @return cookie value
     */
    public static String getCookieVal(HttpServletRequest request, String name) {
        Cookie cookie = getCookie(request, name);
        return cookie != null ? cookie.getValue() : null;
    }

    /**
     * 清除 某个指定的cookie
     *
     * @param response HttpServletResponse
     * @param key cookie key
     */
    public static void removeCookie(HttpServletResponse response, String key) {
        setCookie(response, key, null, 0);
    }

    /**
     * 设置cookie
     *
     * @param response HttpServletResponse
     * @param name cookie name
     * @param value cookie value
     * @param maxAgeInSeconds maxage
     */
    public static void setCookie(HttpServletResponse response, String name, String value, int maxAgeInSeconds) {
        Cookie cookie = new Cookie(name, value);
        cookie.setPath("/");
        cookie.setMaxAge(maxAgeInSeconds);
        cookie.setHttpOnly(true);
        response.addCookie(cookie);
    }

    /**
     * 获取 HttpServletRequest
     *
     * @return {HttpServletRequest}
     */
    public static HttpServletRequest getRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return null;
        }
        return ((ServletRequestAttributes) requestAttributes).getRequest();
    }

    /**
     * 获取ip
     *
     * @return {String}
     */
    public static String getIP() {
        return getIP(WebUtils.getRequest());
    }

    /**
     * 获取ip
     *
     * @param request HttpServletRequest
     * @return {String}
     */
    public static String getIP(HttpServletRequest request) {
        if (request == null) {
            return null;
        }
        String ip = request.getHeader("X-Requested-For");
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (StringUtils.isBlank(ip) || HEADER_IP_UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return StringUtils.isBlank(ip) ? null : ip.split(",")[0];
    }

    /**
     * 获取 X-Kite-Account-Id 用户id
     *
     * @return 用户id 如：123123123123
     */
    public static Long getAccountId() {
        HttpServletRequest request = WebUtils.getRequest();
        if (request == null || kiteProperties == null) {
            return null;
        }
        String accountId = request.getHeader(kiteProperties.getHeaders().getAccountId());
        if (StringUtils.isNotBlank(accountId)) {
            return Long.valueOf(accountId);
        } else {
            return null;
        }
    }

    /**
     * 获取 Kite-X-ACCOUNT 用户头
     *
     * @return 用户id[昵称] 如：123123123123[张三]
     */
    public static String getXAccount() {
        HttpServletRequest request = WebUtils.getRequest();
        if (request == null || kiteProperties == null) {
            return null;
        }
        return request.getHeader(kiteProperties.getHeaders().getXAccount());
    }

    /**
     * 获取 DeviceId
     *
     * @return DeviceId
     */
    public static String getDeviceId() {
        HttpServletRequest request = WebUtils.getRequest();
        if (request == null || kiteProperties == null) {
            return null;
        }
        return request.getHeader(kiteProperties.getHeaders().getDeviceId());
    }

    /**
     * 获取 X-Kite-TOKEN
     *
     * @return X-Kite-TOKEN
     */
    public static String getToken() {
        HttpServletRequest request = WebUtils.getRequest();
        if (request == null || kiteProperties == null) {
            return null;
        }
        String token = WebUtils.getCookieVal(request, kiteProperties.getHeaders().getToken());
        if (StringUtils.isBlank(token)) {
            return request.getHeader(kiteProperties.getHeaders().getToken());
        }
        return token;
    }

    /**
     * 获取 X-Kite-Language
     *
     * @return X-Kite-Language
     */
    public static String getLanguage() {
        String language = kiteLocaleProperties.getDefaultLocale().getLanguage();
        HttpServletRequest request = WebUtils.getRequest();
        if (request == null || kiteProperties == null) {
            return language;
        }
        language = request.getHeader(kiteProperties.getHeaders().getLanguage());
        if (StringUtils.isBlank(language)) {
            language = request.getParameter(kiteLocaleProperties.getParamName());
        }
        if (StringUtils.isBlank(language)) {
            language = request.getLocale().getLanguage();
        }
        return language;
    }
}
